package com.ddfeiyu.client;

import com.alibaba.fastjson.JSON;
import com.ddfeiyu.redis.util.RedisQueueUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Callable;


public class NettyClient implements Callable<Channel> {

    private Logger logger = LoggerFactory.getLogger(NettyClient.class);


    private RedisQueueUtil redisQueueUtil;

    public NettyClient(RedisQueueUtil redisQueueUtil){
        this.redisQueueUtil = redisQueueUtil;
    }


    private EventLoopGroup workerGroup = new NioEventLoopGroup();
    private Channel channel;

    @Override
    public Channel call() throws Exception {
        ChannelFuture channelFuture = null;
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(workerGroup);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.option(ChannelOption.AUTO_READ, true);
            bootstrap.handler(new NettyClientChannelInitializer());

            ServerMeta serverMeta = chooseServer();
            // TODO 方法1： 一、服务端把把自己的地址注册到zk 二、 客户端监听
            // TODO 方法1： 一、服务端把把自己的地址注册到redis 二、 客户端读取
            channelFuture = bootstrap.connect(serverMeta.getHost(), serverMeta.getPort()).syncUninterruptibly();
            this.channel = channelFuture.channel();
        } catch (Exception e) {
            logger.error("socket client start error", e.getMessage());
        } finally {
            if (null != channelFuture && channelFuture.isSuccess()) {
                logger.info("socket client start done. ");
            } else {
                logger.error("socket client start error. ");
            }
        }
        return channel;
    }


    public void destroy() {
        if (null == channel) {
            return;
        }
        channel.close();
        workerGroup.shutdownGracefully();
    }

    public boolean isActive(){
        return channel.isActive();
    }

    public Channel channel() {
        return channel;
    }

    public ServerMeta chooseServer() throws RuntimeException{
        Set<String> allSet = redisQueueUtil.getAllSet(RedisQueueUtil.DDFEIYU_SERVER_QUEUE);
        logger.info("---NettyClient.chooseServer, ServerMeta:[ {} ] ", JSON.toJSONString(allSet));

        Iterator<String> it = allSet.iterator();
        while (it.hasNext()){
            String hostPort = it.next();
            String[] h1 = hostPort.split(":");
            ServerMeta serverMeta = new ServerMeta(h1[0] , Integer.parseInt(h1[1]));
            logger.info("---NettyClient.chooseServer, ServerMeta:[ {} ] ", JSON.toJSONString(serverMeta));
            return serverMeta;
        }
        throw new RuntimeException("服务端未运行");
    }

    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    private class ServerMeta{
        private String host;
        private Integer port;
    }
}
